package com.lp.security.auth.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.lp.biz.member.model.entity.Member;
import com.lp.biz.member.service.MemberService;
import com.lp.common.component.RedisService;
import com.lp.common.context.UserDetail;
import com.lp.common.exception.BaseException;
import com.lp.common.exception.ErrorCodeEnum;
import com.lp.common.utils.CommonResult;
import com.lp.common.utils.RsaUtils;
import com.lp.security.auth.entity.AuthUserDetail;
import com.lp.security.auth.entity.LoginParams;
import com.lp.security.auth.service.AuthService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.HashMap;

import static com.lp.common.constant.CacheConstant.TOKEN_KEY;

/**
 * @program: backend
 * @description:
 * @author: Ke.Song
 * @since: 2024-03-12 21:27:57
 */
@Slf4j
@Service
public class AuthServiceImpl implements AuthService {

    @Autowired
    private RedisService redis;

    @Autowired
    private MemberService memberService;

    /**
     * rsa随机数
     */
    @Value("${rsa.randomNum}")
    private String randomNum;

    @Value("${token.tokenHead}")
    private String tokenHead;

    /**
     * rsa公钥
     */
    @Value("${rsa.publicKey}")
    private String publicKey;

    /**
     * rsa私钥
     */
    @Value("${rsa.privateKey}")
    private String privateKey;

    /**
     * "account": "epDCKK6X0O7CUISogsIhXQYK6Kx6tJoloM1+A6TseqxD3QmdZbd8pu6gcAhyof/UMCscNF2aAbWyjX5H0LA6dWmfpH3gEvaycJ/30a1RoJKRL6GzqqRNw4u5xqFKIW42/4T4PoeLqH0wveDMLdHl12DqtcBVYoQP8wA1d+qCyEU=",
     * "password": "WtnXogTbxUaL5DkZ1HuLx5g8JsRJLrFlL0r0SlAlqMQCbmFh39+RPYRLEWvvN/qeM15tUBaKbs62I+gPLwNuRZiKgg0n/cTb8feQW7u2kjwXdjsTIG0M/ehWDmGKjzQ4gNjopFlGF/nrPrr4/7vAcxPCC8qBYLZCAbTyI15Nulk="
     */
    @Override
    public CommonResult login(LoginParams loginParams) {
        // 校验密码
//        checkPassword(loginParams);
        // 根据账号和密码查询用户信息
        Member member = memberService.getOne(new QueryWrapper<Member>().lambda()
                .eq(Member::getPhone, loginParams.getAccount())
                .eq(Member::getPassword, loginParams.getPassword()));
        // 如果用户不存在，则抛出参数错误异常
        if (member == null) {
            throw new BaseException("账号或密码错误");
        }
        String token;
        try {
            // 尝试使用RSA加密生成token
            token = RsaUtils.encrypt(member.getId() + ":" + randomNum, publicKey);
        } catch (Exception e) {
            // 如果生成token过程中出现异常，记录错误日志并抛出操作失败异常
            log.error("Auth: token error -> {}", e.getMessage());
            throw new BaseException(ErrorCodeEnum.FAILED);
        }
        UserDetail userDetail = memberService.getUserDetail(member.getId());
        AuthUserDetail authUserDetail = new AuthUserDetail();
        authUserDetail.setId(userDetail.getId());
        authUserDetail.setNickName(userDetail.getNickName());
        authUserDetail.setIcon(userDetail.getIcon());
        authUserDetail.setRoles(userDetail.getRoles());
        // 准备登录结果数据
        HashMap<String, Object> result = new HashMap<>(6);
        result.put("token", token);
        result.put("tokenHead", tokenHead);
        result.put("userDetail", authUserDetail);

        redis.put(TOKEN_KEY + member.getId(), token);
        redis.setExpiration(TOKEN_KEY + member.getId(), 43200L);
        // 返回登录成功结果
        return CommonResult.success(result);
    }


    private void checkPassword(LoginParams loginParams) {
        if (loginParams.getAccount() == null || loginParams.getPassword() == null) {
            throw new BaseException(ErrorCodeEnum.PARAMS_ERROR);
        }
        try {
            loginParams.setAccount(RsaUtils.decrypt(loginParams.getAccount(), privateKey));
            loginParams.setPassword(RsaUtils.decrypt(loginParams.getPassword(), privateKey));
        } catch (Exception e) {
            log.error("Auth: account or password error -> {}", e.getMessage());
            throw new BaseException(ErrorCodeEnum.PARAMS_ERROR);
        }
    }
}
